﻿// Fill out your copyright notice in the Description page of Project Settings.


#include "AbilitySystem/Abilities/ProjectileSpell.h"

#include "AbilitySystemBlueprintLibrary.h"
#include "AbilitySystemComponent.h"
#include "Actor/Projectile.h"
#include "Interaction/CombatInterface.h"


void UProjectileSpell::SpawnProjectileWithTargetLocation(
	const FVector& TargetLocation, const FGameplayTag SocketTag, const FName SocketName, bool bOverridePitch, float
	OverridePitch
)
{
	const bool bHasAuthority = GetAvatarActorFromActorInfo()->HasAuthority();
	if (!bHasAuthority)
	{
		return;
	}

	if (const ICombatInterface* CombatInterface = Cast<ICombatInterface>(GetAvatarActorFromActorInfo()))
	{
		const FVector SocketLocation = CombatInterface->Execute_GetCombatSocketLocationByTag(
			GetAvatarActorFromActorInfo(),
			SocketTag,
			SocketName
		);
		// 将方向转为旋转
		FRotator Rotation = (TargetLocation - SocketLocation).Rotation();
		if (bOverridePitch) // 如果指定了OverridePitch，则使用OverridePitch作为Pitch值
		{
			Rotation.Pitch = OverridePitch;
		}

		FTransform SpawnTransform;
		SpawnTransform.SetLocation(SocketLocation);
		SpawnTransform.SetRotation(Rotation.Quaternion());

		// 延迟生成,调用后要调用FinishSpawning确保生成
		AProjectile* Projectile = GetWorld()->SpawnActorDeferred<AProjectile>(
			ProjectileClass,
			SpawnTransform,
			GetOwningActorFromActorInfo(),
			Cast<APawn>(GetAvatarActorFromActorInfo()),
			ESpawnActorCollisionHandlingMethod::AlwaysSpawn
		);


		// ----------------------------------------------------------------------------------------------------------------
		//	创建GE上下文和规格
		// ----------------------------------------------------------------------------------------------------------------

		const UAbilitySystemComponent* SourceASC = GetCurrentActorInfo()->AbilitySystemComponent.Get();

		// 创建一个效果上下文句柄
		FGameplayEffectContextHandle ContextHandle = SourceASC->MakeEffectContext();

		// 将当前技能添加到上下文中
		ContextHandle.SetAbility(this);

		// 将投射物添加为效果的源对象
		ContextHandle.AddSourceObject(Projectile);

		// 将Actor数组添加到上下文句柄中
		TArray<TWeakObjectPtr<AActor>> Actors;
		Actors.Add(Projectile);
		ContextHandle.AddActors(Actors);

		// 将命中结果添加到上下文句柄中
		FHitResult HitResult;
		HitResult.Location = TargetLocation;
		ContextHandle.AddHitResult(HitResult);

		// 将目标位置作为效果的源位置添加到上下文句柄中
		ContextHandle.AddOrigin(TargetLocation);

		const FGameplayEffectSpecHandle GESpecHandle = SourceASC->MakeOutgoingSpec(
			DamageEffectClass,
			GetAbilityLevel(),
			ContextHandle
		);


		// 遍历DamageTypeToDamage，将SetByCallerGE的值设置为对应标签的伤害值
		for (auto& TypeToDamageMap : DamageTypeToDamage)
		{
			const float Magnitude = TypeToDamageMap.Value.GetValueAtLevel(GetAbilityLevel());
			//设置Tag对应SetByCallerGE的值
			UAbilitySystemBlueprintLibrary::AssignTagSetByCallerMagnitude(GESpecHandle, TypeToDamageMap.Key, Magnitude);
		}

		/** 将GESpecHandle传递给Projectile */
		Projectile->DamageEffectHandle = GESpecHandle;


		// 延迟生成调用后要调用FinishSpawning确保生成
		Projectile->FinishSpawning(SpawnTransform);
	}
}
